#include <iostream>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;

#define MAX 1024


// a. 管道的四种情况
//       1.正常情况，如果管道满了,写端必须等待，知道有空间为止（读端读走数据）
//       2.正常情况，如果管道中没有数据,读端必须等待（阻塞），直到管道中有数据为止（读端写入）   
//       3.写端异常，读端直接读到0
//       4.读端异常。写端在写入就已经没有意义了，os发送信号SIGPIPE(13)杀死进程       
//
// b. 管道的五种特性
//       1.匿名管道只允许具有亲缘关系的进程进行进程间通信
//       2.管道默认为两个进程提供了一种同步机制
//       3.面相字节流
//       4.管道生命周期是随进程的
//       5.匿名管道是单向通信的,属于半双工的一种特殊情况


int main()
{

    // 子写 父读
    // 第一步打开文件读写端
    int pipefd[2] = {0};
    int n = pipe(pipefd);
    cout << "pipefd[0]: " << pipefd[0] << " pipefd[1]: " << pipefd[1] << endl;
    assert(n == 0);
    (double)n; // 防止为被使用，编译器告警

    // 第二步创建子进程
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return 1;
    }
    if (id == 0)
    {
        // child
        close(pipefd[0]);
        int cnt = 0;
        char msg[MAX];

        char ch = 'a';
        while (true)
        {

            // write(pipefd[1],&ch,1);
            // cnt++;
            // cout<< "write... : "<<cnt<<endl;

            snprintf(msg, sizeof(msg), "%d , hello father ! I am child pid : %d", cnt, getpid());
            write(pipefd[1], msg, strlen(msg));
            cnt++;
            //sleep(1);
            cout<< "write .... "<<endl;
        }

       
        exit(0);
    }

    // 第三步关闭对应的读写端
    // father
    close(pipefd[1]);
    //关闭读端 
    //close(pipefd[0]);
    char buff[MAX];
    while (true)
    {
        
        //bug
        ssize_t n = read(pipefd[0], buff, sizeof(buff) - 1);
        if (n > 0)
        {
            buff[n] = '\0'; // 手动添加字符串结尾标志
            cout <<getpid()<<","<< "child say :"<< "readsize : "<< n <<buff << endl;
        }
        else if(n == 0) 
        {
            cout<<"child quit ! me to ! "<<endl;
            break;
        }
        else{
            //文件描述符关闭，读取异常返回-1
            cout<< "return val : " << n <<endl;
            break;
        }
    }
    
    //进程等待
    int status = 0;
    pid_t rid = waitpid(id,&status,0);
    if(rid == id)
    {
        cout<<"wait success chile sig : "<< (status&0x7F) << endl;
    }

    return 0;
}
